﻿using AutoNyaa.Logic.Entities;
using System.Collections.Generic;
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Threading;
namespace AutoNyaa.Logic
{
    public class FilterManager
    {
        public string SaveFile { get; set; }

        public int Delay { get; set; }

        public string Url { get; set; }

        private bool _exit;

        private bool _filtersUpdated;

        public SavedFilters SavedFilters { get; set; }

        public List<Filter> Filters
        {
            get
            {
                return SavedFilters.Filters;
            }
            set
            {
                SavedFilters.Filters = value;
            }
        }

        #region Delegates

        public delegate void FiltersUpdatedHandler();
        public delegate void DownloadItemDetectedHandler(Item item);

        public event FiltersUpdatedHandler FiltersUpdated;
        public event DownloadItemDetectedHandler DownloadItemDetected;

        #endregion

        public FilterManager()
        {
            Delay = Properties.UserSettings.Default.FilterDelay;
            SaveFile = Properties.UserSettings.Default.FiltersSaveFile;
            Url = Properties.UserSettings.Default.RssUrl;

            _exit = false;
            _filtersUpdated = false;

            SavedFilters = new SavedFilters();
        }

        public void Run()
        {
            LoadFilters();

            while (!_exit)
            {
                CheckFilters();

                for (int i = 0; i < Delay && !_exit; i++)
                {
                    Thread.Sleep(1000);
                }
            }
            SaveFilters();
        }

        private void CheckFilters()
        {
            if (DateTime.Now.Subtract(SavedFilters.LastUpdated).Days >= 1)
            {
                CheckFiltersLong();
            }
            else
            {
                CheckFiltersShort();
            }
        }

        private void CheckFiltersLong()
        {
            foreach (Filter filter in Filters)
            {
                int page = 1;

                RssFeed feed = RssFeed.Deserialize(new Uri(Url), page, filter.SearchString, filter.Category.Value, filter.TypeFilter.Value);

                if (feed == null || feed.Items == null || feed.Items.Count == 0)
                {
                    break;
                }

                foreach (Item item in feed.Items)
                {
                    if (item.PublishDate.CompareTo(filter.LastUpdated) == -1)
                    {
                        filter.LastUpdated = DateTime.Now;
                        break;
                    }
                    if (filter.Validates(item.Title))
                    {
                        OnDownloadItemDetected(item);
                    }
                }
                page++;
            }
            SavedFilters.LastUpdated = DateTime.Now;
        }

        private void CheckFiltersShort()
        {
            int page = 1;

            while (Filters.Count > 0)
            {
                RssFeed feed = RssFeed.Deserialize(new Uri(Url), page);

                if (feed == null || feed.Items == null || feed.Items.Count == 0)
                {
                    break;
                }

                foreach (Item item in feed.Items)
                {
                    if (item.PublishDate.CompareTo(SavedFilters.LastUpdated) == -1)
                    {
                        SavedFilters.LastUpdated = DateTime.Now;
                        return;
                    }
                    foreach (Filter filter in Filters)
                    {
                        if (filter.Validates(item.Title))
                        {
                            filter.LastUpdated = DateTime.Now;
                            OnDownloadItemDetected(item);
                             break;
                        }
                    }
                }

                page++;
            }

        }

        public void LoadFilters()
        {
            XmlTextReader reader = null;

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SavedFilters));

                if (!Directory.Exists(Path.GetDirectoryName(SaveFile)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(SaveFile));
                }
                if (!File.Exists(SaveFile))
                {
                    SaveFilters();
                }

                reader = new XmlTextReader(SaveFile);
                SavedFilters = (SavedFilters)serializer.Deserialize(reader);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                reader.Close();
            }
            OnFiltersUpdated();
        }

        public void SaveFilters()
        {
            StreamWriter streamWriter = null;

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SavedFilters));
                streamWriter = new StreamWriter(SaveFile);

                serializer.Serialize(streamWriter, SavedFilters);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                streamWriter.Close();
            }
        }

        public void Exit()
        {
            _exit = true;
        }

        public void AddFilter(Filter filter)
        {
            Filters.Add(filter);
            SaveFilters();
            OnFiltersUpdated();
        }

        public void RemoveFilter(Filter filter)
        {
            Filters.Remove(filter);
            SaveFilters();
            OnFiltersUpdated();
        }

        #region Event Methods

        protected void OnFiltersUpdated()
        {
            if (FiltersUpdated != null)
            {
                FiltersUpdated();
            }
        }

        protected void OnDownloadItemDetected(Item item)
        {
            if (DownloadItemDetected != null)
            {
                DownloadItemDetected(item);
            }
        }

        #endregion
    }
}